package boardgamer.yavalath.client.lobby;

import android.graphics.Canvas;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.MotionEvent;
import boardgamer.common.CheckedCyclicIterator;
import boardgamer.common.client.Button;
import boardgamer.common.client.ClickableButton;
import boardgamer.common.client.Display;
import boardgamer.common.client.Drawable;
import boardgamer.common.client.HasEventHandler;
import boardgamer.common.client.layout.HasLayout;
import boardgamer.common.client.layout.MutableBitmapLayout;
import boardgamer.yavalath.client.RenderHelper;
import boardgamer.yavalath.client.Settings;
import boardgamer.yavalath.client.resources.ImageHandler;
import boardgamer.yavalath.client.resources.SoundHandler;
import boardgamer.yavalath.common.YavalathPlayerState;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * @author garysoed
 */
public class PlayerColorPicker implements Drawable, HasLayout, HasEventHandler {

  private final int playerId;
  private final CheckedCyclicIterator<YavalathPlayerState.PlayerColor> playerColorIterator;
  private final ClickableButton button;
  private final InnerButton innerButton;
  private final InnerButtonGlow innerButtonGlow;

  public PlayerColorPicker(
      int playerId, Predicate<YavalathPlayerState.PlayerColor> playerColorPredicate) {
    this.playerId = playerId;

    YavalathPlayerState.PlayerColor playerColor
        = Settings.instance().getPlayer(playerId).getColor();
    int color = RenderHelper.instance().getColor(playerColor);
    Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    backgroundPaint.setColorFilter(new LightingColorFilter(color, 0));

    this.innerButton = new InnerButton(backgroundPaint);
    this.innerButtonGlow = new InnerButtonGlow(backgroundPaint);
    this.button = new ClickableButton(innerButton, innerButtonGlow);
    this.playerColorIterator = new CheckedCyclicIterator<YavalathPlayerState.PlayerColor>(
        getPlayerColorList(playerColor), playerColorPredicate);
  }

  private List<YavalathPlayerState.PlayerColor> getPlayerColorList(
      YavalathPlayerState.PlayerColor playerColor) {
    List<YavalathPlayerState.PlayerColor> allColors
        = ImmutableList.copyOf(YavalathPlayerState.PlayerColor.values());
    int playerColorIndex = allColors.indexOf(playerColor);
    List<YavalathPlayerState.PlayerColor> firstSublist
        = allColors.subList(playerColorIndex, allColors.size());
    List<YavalathPlayerState.PlayerColor> secondSublist = allColors.subList(0, playerColorIndex);

    List<YavalathPlayerState.PlayerColor> reversedList = Lists.newArrayList();
    reversedList.addAll(firstSublist);
    reversedList.addAll(secondSublist);
    return ImmutableList.copyOf(reversedList);
  }

  @Override
  public void draw(Canvas canvas) {
    button.draw(canvas);
  }

  @Override
  public void handleEvent(float eventX, float eventY, int eventAction) {
    button.handleEvent(eventX, eventY, eventAction);
  }

  @Override
  public RectF getCollisionBox() {
    return button.getCollisionBox();
  }

  @Override
  public void setBoundingRect(RectF boundingRect) {
    button.setBoundingRect(boundingRect);
  }

  @Override
  public RectF getBoundingRect() {
    return button.getBoundingRect();
  }

  private void changeColor() {
    YavalathPlayerState.PlayerColor newPlayerColor = playerColorIterator.next();
    int newColor = RenderHelper.instance().getColor(newPlayerColor);
    Settings.instance().setPlayerColor(playerId, newPlayerColor);
    innerButton.setColor(newColor);
    innerButtonGlow.setColor(newColor);
  }

  public YavalathPlayerState.PlayerColor getPlayerColor() {
    return Settings.instance().getPlayer(playerId).getColor();
  }

  private class InnerButton implements Button {

    private final Paint backgroundPaint;
    private MutableBitmapLayout background;

    public InnerButton(Paint backgroundPaint) {
      this.backgroundPaint = checkNotNull(backgroundPaint, "backgroundPaint");
      this.background = new MutableBitmapLayout(ImageHandler.colorPicker, backgroundPaint);
    }

    @Override
    public void draw(Canvas canvas) {
      background.draw(canvas);
    }

    @Override
    public void handleEvent(float eventX, float eventY, int eventAction) {
      if (eventAction == MotionEvent.ACTION_UP && getCollisionBox().contains(eventX, eventY)) {
        SoundHandler.playWave(SoundHandler.buttonSound);
        PlayerColorPicker.this.changeColor();
      }
    }

    @Override
    public RectF getCollisionBox() {
      return getBoundingRect();
    }

    @Override
    public void setBoundingRect(RectF boundingRect) {
      background.setBoundingRect(boundingRect);
    }

    @Override
    public RectF getBoundingRect() {
      return background.getBoundingRect();
    }

    public void setColor(int color) {
      this.backgroundPaint.setColorFilter(new LightingColorFilter(color, 0));
      this.background.setPaint(this.backgroundPaint);
    }
  }

  private class InnerButtonGlow implements Display {

    private final Paint glowPaint;
    private MutableBitmapLayout glow;

    public InnerButtonGlow(Paint glowPaint) {
      this.glowPaint = checkNotNull(glowPaint, "glowPaint");
      this.glow = new MutableBitmapLayout(ImageHandler.colorPickerGlow, glowPaint);
    }

    @Override
    public void draw(Canvas canvas) {
      glow.draw(canvas);
    }

    @Override
    public void setBoundingRect(RectF boundingRect) {
      glow.setBoundingRect(boundingRect);
    }

    @Override
    public RectF getBoundingRect() {
      return glow.getBoundingRect();
    }

    public void setColor(int color) {
      this.glowPaint.setColorFilter(new LightingColorFilter(color, 0));
      this.glow.setPaint(glowPaint);
    }
  }
}
